home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / tcp_ip / ntp_src / ntp_rest.c < prev    next >
C/C++ Source or Header  |  1992-04-03  |  7KB  |  298 lines

  1. /*
  2.  * ntp_restrict.c - find out what restrictions this host is running under
  3.  */
  4. #include <stdio.h>
  5.  
  6. #include "global.h"
  7. #include "sockaddr.h"
  8.  
  9. #include "ntp_types.h"
  10. #include "ntp_syslog.h"
  11. #include "ntp_fp.h"
  12. #include "ntp.h"
  13.  
  14.  
  15. /*
  16.  * This code keeps a simple address-and-mask list of hosts we want
  17.  * to place restrictions on (or remove them from).  The restrictions
  18.  * are implemented as a set of flags which tell you what the host
  19.  * can't do.  There is a subroutine entry to return the flags.  The
  20.  * list is kept sorted to reduce the average number of comparisons
  21.  * and make sure you get the set of restrictions most specific to
  22.  * the address.
  23.  *
  24.  * The algorithm is that, when looking up a host, it is first assumed
  25.  * that the default set of restrictions will apply.  It then searches
  26.  * down through the list.  Whenever it finds a match it adopts the match's
  27.  * flags instead.  When you hit the point where the sorted address is
  28.  * greater than the target, you return with the last set of flags you
  29.  * found.  Because of the ordering of the list, the most specific match
  30.  * will provide the final set of flags.
  31.  *
  32.  * This was originally intended to restrict you from sync'ing to your
  33.  * own broadcasts when you are doing that, by restricting yourself
  34.  * from your own interfaces.  It was also thought it would sometimes
  35.  * be useful to keep a misbehaving host or two from abusing your primary
  36.  * clock.  It has been expanded, however, to suit the needs of those
  37.  * with more restrictive access policies.
  38.  */
  39.  
  40. /*
  41.  * Memory allocation parameters.  We allocate INITRESLIST entries
  42.  * initially, and add INCRESLIST entries to the free list whenever
  43.  * we run out.
  44.  */
  45. #define    INITRESLIST    10
  46. #define    INCRESLIST    5
  47.  
  48. /*
  49.  * The restriction list
  50.  */
  51. struct restrictlist *restrictlist;
  52. int restrictcount;    /* count of entries in the restriction list */
  53.  
  54. /*
  55.  * The free list and associated counters.  Also some uninteresting
  56.  * stat counters.
  57.  */
  58. struct restrictlist *resfree;
  59. int numresfree;        /* number of structures on free list */
  60.  
  61. u_long res_calls;
  62. u_long res_found;
  63. u_long res_not_found;
  64. u_long res_timereset;
  65.  
  66. /*
  67.  * Our initial allocation of list entries.
  68.  */
  69. struct restrictlist resinit[INITRESLIST];
  70.  
  71.  
  72. /*
  73.  * init_restrict - initialize the restriction data structures
  74.  */
  75. void
  76. init_restrict()
  77. {
  78.     register int i;
  79.  
  80.     /*
  81.      * Zero the list and put all but one on the free list
  82.      */
  83.     resfree = 0;
  84.     bzero((char *)resinit, sizeof resinit);
  85.  
  86.     for (i = 1; i < INITRESLIST; i++) {
  87.         resinit[i].next = resfree;
  88.         resfree = &resinit[i];
  89.     }
  90.  
  91.     numresfree = INITRESLIST-1;
  92.  
  93.     /*
  94.      * Put the remaining item at the head of the
  95.      * list as our default entry.  Everything in here
  96.      * should be zero for now.
  97.      */
  98.     resinit[0].addr = INADDR_ANY;
  99.     resinit[0].mask = 0;
  100.     restrictlist = &resinit[0];
  101.     restrictcount = 1;
  102.  
  103.  
  104.     /*
  105.      * fix up stat counters
  106.      */
  107.     res_calls = 0;
  108.     res_found = 0;
  109.     res_not_found = 0;
  110.     res_timereset = 0;
  111. }
  112.  
  113.  
  114. /*
  115.  * restrictions - return restrictions for this host
  116.  */
  117. int
  118. restrictions(srcadr)
  119.     struct sockaddr_in *srcadr;
  120. {
  121.     register struct restrictlist *rl;
  122.     register struct restrictlist *match;
  123.     register u_long hostaddr;
  124.     register int isntpport;
  125.  
  126.     res_calls++;
  127.     /*
  128.      * We need the host address in host order.  Also need to know
  129.      * whether this is from the ntp port or not.
  130.      */
  131.     hostaddr = SRCADR(srcadr);
  132.     isntpport = (SRCPORT(srcadr) == NTP_PORT);
  133.  
  134.     /*
  135.      * Set match to first entry, which is default entry.  Work our
  136.      * way down from there.
  137.      */
  138.     match = restrictlist;
  139.  
  140.     for (rl = match->next; rl != 0 && rl->addr <= hostaddr; rl = rl->next)
  141.         if ((hostaddr & rl->mask) == rl->addr) {
  142.             if ((rl->mflags & RESM_NTPONLY) && !isntpport)
  143.                     continue;
  144.             match = rl;
  145.         }
  146.  
  147.     match->count++;
  148.     if (match == restrictlist)
  149.         res_not_found++;
  150.     else
  151.         res_found++;
  152.     
  153.     return (int)match->flags;
  154. }
  155.  
  156.  
  157. /*
  158.  * restrict - add/subtract/manipulate entries on the restrict list
  159.  */
  160. void
  161. restrict(op, resaddr, resmask, mflags, flags)
  162.     int op;
  163.     struct sockaddr_in *resaddr;
  164.     struct sockaddr_in *resmask;
  165.     int mflags;
  166.     int flags;
  167. {
  168.     register u_long addr;
  169.     register u_long mask;
  170.     register struct restrictlist *rl;
  171.     register struct restrictlist *rlprev;
  172.     int i;
  173.  
  174.     /*
  175.      * Get address and mask in host byte order
  176.      */
  177.     addr = SRCADR(resaddr);
  178.     mask = SRCADR(resmask);
  179.     addr &= mask;        /* make sure low bits are zero */
  180.  
  181.     /*
  182.      * If this is the default address, point at first on list.  Else
  183.      * go searching for it.
  184.      */
  185.     if (addr == INADDR_ANY) {
  186.         rlprev = 0;
  187.         rl = restrictlist;
  188.     } else {
  189.         rlprev = restrictlist;
  190.         rl = rlprev->next;
  191.         while (rl != 0) {
  192.             if (rl->addr > addr) {
  193.                 rl = 0;
  194.                 break;
  195.             } else if (rl->addr == addr) {
  196.                 if (rl->mask == mask) {
  197.                     if ((mflags & RESM_NTPONLY)
  198.                         == (rl->mflags & RESM_NTPONLY))
  199.                         break;    /* exact match */
  200.                     if (!(mflags & RESM_NTPONLY)) {
  201.                         /*
  202.                          * No flag fits before flag
  203.                          */
  204.                         rl = 0;
  205.                         break;
  206.                     }
  207.                     /* continue on */
  208.                 } else if (rl->mask > mask) {
  209.                     rl = 0;
  210.                     break;
  211.                 }
  212.             }
  213.             rlprev = rl;
  214.             rl = rl->next;
  215.         }
  216.     }
  217.     /*
  218.      * In case the above wasn't clear :-), either rl now points
  219.      * at the entry this call refers to, or rl is zero and rlprev
  220.      * points to the entry prior to where this one should go in
  221.      * the sort.
  222.      */
  223.  
  224.     /*
  225.      * Switch based on operation
  226.      */
  227.     switch (op) {
  228.     case RESTRICT_FLAGS:
  229.         /*
  230.          * Here we add bits to the flags.  If this is a new
  231.          * restriction add it.
  232.          */
  233.         if (rl == 0) {
  234.             if (numresfree == 0) {
  235.                 rl = (struct restrictlist *) mallocw(
  236.                     INCRESLIST*sizeof(struct restrictlist));
  237.                 bzero((char *)rl,
  238.                     INCRESLIST*sizeof(struct restrictlist));
  239.  
  240.                 for (i = 0; i < INCRESLIST; i++) {
  241.                     rl->next = resfree;
  242.                     resfree = rl;
  243.                     rl++;
  244.                 }
  245.                 numresfree = INCRESLIST;
  246.             }
  247.  
  248.             rl = resfree;
  249.             resfree = rl->next;
  250.             numresfree--;
  251.  
  252.             rl->addr = addr;
  253.             rl->mask = mask;
  254.             rl->mflags = (u_short)mflags;
  255.  
  256.             rl->next = rlprev->next;
  257.             rlprev->next = rl;
  258.             restrictcount++;
  259.         }
  260.         rl->flags |= (u_short)flags;
  261.         break;
  262.     
  263.     case RESTRICT_UNFLAG:
  264.         /*
  265.          * Remove some bits from the flags.  If we didn't
  266.          * find this one, just return.
  267.          */
  268.         if (rl != 0)
  269.             rl->flags &= (u_short)~flags;
  270.         break;
  271.     
  272.     case RESTRICT_REMOVE:
  273.         /*
  274.          * Remove an entry from the table entirely if we found one.
  275.          * Don't remove the default entry and don't remove an
  276.          * interface entry.
  277.          */
  278.         if (rl != 0
  279.             && rl->addr != INADDR_ANY
  280.             && !(rl->mflags & RESM_INTERFACE)) {
  281.             rlprev->next = rl->next;
  282.             restrictcount--;
  283.             bzero((char *)rl, sizeof(struct restrictlist));
  284.  
  285.             rl->next = resfree;
  286.             resfree = rl;
  287.             numresfree++;
  288.         }
  289.         break;
  290.  
  291.     default:
  292.         /* Oh, well */
  293.         break;
  294.     }
  295.  
  296.     /* done! */
  297. }
  298.